﻿using System;
using System.IO;
using System.IO.Compression;
using System.Text;
using Shinkansen.Core;

namespace Shinkansen.Support
{
    public class HttpCompressor
    {
        private readonly HttpCompressionMode _mode;

        /// <summary>
        /// Initializes a new instance of the <see cref="HttpCompressor"/> class.
        /// </summary>
        /// <param name="mode">The mode.</param>
        public HttpCompressor (HttpCompressionMode mode)
        {
            _mode = mode;
        }

        /// <summary>
        /// Compresses content represented as a byte array.
        /// </summary>
        /// <param name="content">The content.</param>
        /// <returns></returns>
        public byte[] Compress (byte[] content)
        {
            using (MemoryStream ms = new MemoryStream ())
            using (Stream stream = CreateCompressionStream (ms))
            {
                stream.Write (content, 0, content.Length);
                stream.Close ();

                return ms.ToArray ();
            }
        }

        /// <summary>
        /// Compresses content represented as plain text.
        /// </summary>
        /// <param name="content">The content.</param>
        /// <returns></returns>
        public string Compress (string content)
        {
            byte[] contentBytes = Encoding.UTF8.GetBytes (content);
            byte[] compressedBytes = Compress (contentBytes);

            return Encoding.UTF8.GetString (compressedBytes);
        }

        /// <summary>
        /// Creates the compression stream.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <returns></returns>
        private Stream CreateCompressionStream (Stream stream)
        {
            Stream compressionStream;

            switch (_mode)
            {
                case HttpCompressionMode.Deflate:
                    compressionStream = new DeflateStream (stream, CompressionMode.Compress);
                    break;

                case HttpCompressionMode.GZip:
                    compressionStream = new GZipStream (stream, CompressionMode.Compress);
                    break;

                default:
                    throw new InvalidOperationException ("HTTP compression type has not been specified.");
            }

            return compressionStream;
        }
    }
}